/*
 * Title:        CloudScheduler Toolkit
 * Description:  a Toolkit for Modeling and Simulation of Job Scheduling and Resource Provisioning in Cloud System
 * Licence:      GPL - http://www.gnu.org/copyleft/gpl.html
 * Author:       Fuhui Wu
 *
 * Copyright (c) 2013-2014, The National University of Defense Technology, China
 */

package org.nudt.jCloud.example.resourceStealing1;

import java.util.ArrayList;
import java.util.List;

import org.nudt.jCloud.infrastructure.Slot;
import org.nudt.jCloud.infrastructure.SlotType;
import org.nudt.jCloud.resourceScaler.ResourceScaler;
import org.nudt.jCloud.simulation.CloudSchedSIM;
import org.nudt.jCloud.simulation.Request;
import org.nudt.jCloud.simulation.RequestData;
import org.nudt.jCloud.simulation.SIMTag;
import org.nudt.jCloud.simulation.ScaleData;

public class TransScaler extends ResourceScaler{
	private SlotType slotType;
	private int slotNum;
	private boolean scaled;
	private List<Slot> stolenSlotList;
	private List<Slot> usedSlotList;
	
	public TransScaler(SlotType slotType, int slotNum){
		super();
		setSlotType(slotType);
		setSlotNum(slotNum);
		scaled = false;
		stolenSlotList = new ArrayList<Slot>();
		usedSlotList = new ArrayList<Slot>();
	}	

	@Override
	public void specialReset() {
		scaled = false;
		stolenSlotList.clear();
		usedSlotList.clear();
	}

	@Override
	public void scaleResource(RequestData requestData, ScaleData scaleData) {
		if(scaled == false){
			scaleData.getToLeaseSlot().put(slotType, slotNum);
			setScaled(true);
		}else{
			Request request = requestData.getRequestList().get(0);
			SlotType slotType = request.getJob().getSlotType();
			int requestSize = request.getUnAssignedTasks().size();
			List<Slot> freeSlotList = getFrwk().getFreeSlots().get(slotType);
			stolenSlotList.addAll(freeSlotList);
			stolenSlotList.removeAll(usedSlotList);
			freeSlotList.clear();
			freeSlotList.addAll(usedSlotList);
			if(usedSlotList.size()>requestSize){
				List<Slot> stealingSlotList = new ArrayList<Slot>();
				int deta = usedSlotList.size()-requestSize;
				for(int i=0; i<deta; ++i){
					Slot slot = freeSlotList.get(0);
					freeSlotList.remove(slot);
					usedSlotList.remove(slot);
					stolenSlotList.add(slot);
					stealingSlotList.add(slot);
				}
				getFrwk().getUserBroker().sendNow(CloudSchedSIM.getEntityIdByName("UserBroker2"),
						SIMTag.TO_STEAL_RESOURCE, stealingSlotList);
			}else{
				List<Slot> preemptSlotList = new ArrayList<Slot>();
				int deta = requestSize-usedSlotList.size();
				for(int i=0; i<deta; ++i){
					Slot slot = stolenSlotList.get(0);
					freeSlotList.add(slot);
					usedSlotList.add(slot);
					stolenSlotList.remove(slot);
					preemptSlotList.add(slot);
					getFrwk().getUserBroker().sendNow(CloudSchedSIM.getEntityIdByName("UserBroker2"),
							SIMTag.PREEMPT_STOLEN_SLOT, preemptSlotList);
				}
			}
		}
	}
	
	public int getSlotNum(){
		return slotNum;
	}
	
	public void setSlotNum(int slotNum){
		this.slotNum = slotNum;
	}
	
	public boolean isScaled(){
		return scaled;
	}
	
	public void setScaled(boolean scaled){
		this.scaled = scaled;
	}

	public SlotType getSlotType() {
		return slotType;
	}

	public void setSlotType(SlotType slotType) {
		this.slotType = slotType;
	}

	public List<Slot> getUsedSlotList() {
		return usedSlotList;
	}

	public void setUsedSlotList(List<Slot> usedSlotList) {
		this.usedSlotList = usedSlotList;
	}

	public List<Slot> getStolenSlotList() {
		return stolenSlotList;
	}

	public void setStolenSlotList(List<Slot> stolenSlotList) {
		this.stolenSlotList = stolenSlotList;
	}

}
